#include "fifo.h"

static unsigned char fifo_read_wrap(unsigned char* pcData);
static unsigned char fifo_write_wrap(unsigned char cData);

static unsigned char fifo_Buf[FIFO_BUFSIZE];

static fifo_t uart_fifo = {
    .cBuf = &fifo_Buf,
    .cBufSize = FIFO_BUFSIZE,
    .cWIdx = 0,
    .cRIdx = 0,
    .read = fifo_read_wrap,
    .write = fifo_write_wrap,
};

fifo_t* fifo_info(void)
{
    return (&uart_fifo);
}

void fifo_init(fifo_t* fifo, unsigned char* pBuf, unsigned int buf_size)
{
    fifo->cBuf = pBuf;
    fifo->cBufSize = buf_size;

    for (unsigned int i = 0; i < fifo->cBufSize; i++)
        fifo->cBuf[i] = 0;

    fifo->cWIdx = 0;
    fifo->cRIdx = 0;
}

unsigned char fifo_write(fifo_t* fifo, unsigned char cData)
{
    unsigned char cRet = 1;

    if (((fifo->cWIdx + 1) % fifo->cBufSize) == fifo->cRIdx) {
        fifo->cRIdx = (fifo->cRIdx + 1) % fifo->cBufSize;
        cRet = 0;
    }
    fifo->cBuf[fifo->cWIdx] = cData;
    fifo->cWIdx = (fifo->cWIdx + 1) % fifo->cBufSize;

    return (cRet);
}

unsigned char fifo_read(fifo_t* fifo, unsigned char* pcData)
{
    unsigned char cRet = 1;
    unsigned int widx = 0;

    widx = fifo->cWIdx;

    if (fifo->cRIdx == widx) {
        cRet = 0;
    } else {
        *pcData = fifo->cBuf[fifo->cRIdx];
        fifo->cRIdx = (fifo->cRIdx + 1) % fifo->cBufSize;
    }

    return (cRet);
}

unsigned char fifo_read_wrap(unsigned char* pcData)
{
    return fifo_read(fifo_info(), pcData);
}

unsigned char fifo_write_wrap(unsigned char cData)
{
    return fifo_write(fifo_info(), cData);
}